/*
 * @Description: 事件hooks
 * @Author: seadon
 * @LastEditors: seadon
 * @Date: 2021-07-28 17:26:41
 * @LastEditTime: 2021-08-05 14:03:03
 */
import { ref, Ref, watch, unref } from 'vue'
import { debounce, throttle } from 'lodash'

export type RemoveEventFn = () => void

export interface UseEventParams {
	el?: Element | Ref<Element | undefined> | Window | any
	name: string
	listener: EventListener
	options?: boolean | AddEventListenerOptions
	autoRemove?: boolean
	isDebounce?: boolean
	wait?: number
}
export function useEventListener({
	el = window,
	name,
	listener,
	options,
	autoRemove = true,
	isDebounce = true,
	wait = 80,
}: UseEventParams): { removeEvent: RemoveEventFn } {
	/* eslint-disable-next-line */
	let remove: RemoveEventFn = () => {}
	const isAddRef = ref(false)

	if (el) {
		const element: any = ref(el as Element)

		const handler = isDebounce
			? debounce(listener, wait)
			: throttle(listener, wait)
		const realHandler = wait ? handler : listener
		const removeEventListener = (e: Element) => {
			isAddRef.value = true
			e.removeEventListener(name, realHandler, options)
		}
		const addEventListener = (e: Element) =>
			e.addEventListener(name, realHandler, options)

		const removeWatch = watch(
			element,
			(v, _ov, cleanUp) => {
				if (v) {
					!unref(isAddRef) && addEventListener(v as any)
					cleanUp(() => {
						autoRemove && removeEventListener(v as any)
					})
				}
			},
			{ immediate: true }
		)

		remove = () => {
			removeEventListener(element.value)
			removeWatch()
		}
	}
	return { removeEvent: remove }
}
